package cn.zmit.kuxi.application;

import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.Date;

import android.annotation.SuppressLint;
import android.app.Application;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Build;
import android.os.Environment;
import android.os.Looper;
import android.telephony.TelephonyManager;
import android.widget.Toast;
import cn.zmit.kuxi.contants.Constants;

import com.lidroid.xutils.util.LogUtils;
import com.xdroid.utils.AppManager;

@SuppressLint("SimpleDateFormat")
public class AppExceptionHandler implements Thread.UncaughtExceptionHandler {
	private StringBuffer sb = new StringBuffer();

	private static final String VERSION_NAME = "versionName";

	private static final String VERSION_CODE = "versionCode";

	private static final String CRASH_TIME = "crashTime";

	private static final String PET_NAME = "petName";

	private static final String CRASH_REPORTER_EXTENSION = ".log";

	private Application softApp;

	public AppExceptionHandler(Application application) {
		softApp = application;
	}

	/**
	 * 当UncaughtException发生时会转入该函数来处理
	 */
	public void uncaughtException(Thread thread, Throwable ex) {

		// 保存CrashLog到本地
		saveCrashInfoToFile(ex, 1);

		// 执行子线程弹出提示
		handleException("程序运行异常,即将退回上一界面！", ex);

		// 延时3秒杀死当前进程
		try {
			Thread.sleep(3000);
		} catch (InterruptedException e) {
		}
		AppManager.getInstance().killTopActivity();
		android.os.Process.killProcess(android.os.Process.myPid());
	}

	/**
	 * 保存CrashLog到文件
	 * 
	 * @param ex
	 * @param flag
	 * @return
	 */
	public String saveCrashInfoToFile(Throwable ex, int flag) {
		Writer info = new StringWriter();
		PrintWriter printWriter = new PrintWriter(info);
		ex.printStackTrace(printWriter);
		ex.printStackTrace();
		Throwable cause = ex.getCause();
		while (cause != null) {
			cause.printStackTrace(printWriter);
			cause = cause.getCause();
		}
		String result = info.toString();
		printWriter.close();
		// 在Log控制台打印错误日志
		LogUtils.e("Crash错误信息:" + result);

		// 收集设备信息
		collectCrashDeviceInfo(softApp.getApplicationContext());

		// 保存崩溃的堆栈记录和时间
		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss");
		sb.append(CRASH_TIME + "=").append(df.format(new Date())).append("\n")
				.append("STACK_TRACE" + "=").append(result);
		try {
			String fileName;
			if (flag == 1)
				fileName = "crash-" + df.format(new Date())
						+ CRASH_REPORTER_EXTENSION;
			else
				fileName = "error-" + df.format(new Date())
						+ CRASH_REPORTER_EXTENSION;

			File crashLogPath = null;
			File root = Environment.getExternalStorageDirectory();
			if (android.os.Environment.getExternalStorageState().equals(
					android.os.Environment.MEDIA_MOUNTED)) {
				crashLogPath = new File(root.getAbsolutePath() + File.separator
						+ Constants.BASE_PATH + "CrashLog");
			}
			if (!crashLogPath.exists()) {
				crashLogPath.mkdirs();
			}
			if (crashLogPath != null && !crashLogPath.exists()) {
				crashLogPath.mkdirs();
			}
			// 创建文件
			File file = new File(crashLogPath, fileName);
			FileOutputStream outStream = new FileOutputStream(file);
			outStream.write(sb.toString().getBytes("utf-8"));
			outStream.flush();
			outStream.close();
			return fileName;
		} catch (Exception e) {
			LogUtils.i(e.toString());
		}
		// end
		return null;
	}

	/**
	 * 收集设备信息
	 * 
	 * @param ctx
	 */
	public void collectCrashDeviceInfo(Context ctx) {

		try {
			PackageManager pm = ctx.getPackageManager();
			PackageInfo pi = pm.getPackageInfo(ctx.getPackageName(),
					PackageManager.GET_ACTIVITIES);
			if (pi != null) {
				sb.append(PET_NAME + "=")
						.append(Build.MODEL)
						.append("\n")
						.append(VERSION_NAME + "=")
						// 版本名称
						.append(pi.versionName == null ? "not set"
								: pi.versionName)
						.append("\n")

						// .append(RESOLUTION + "=")
						// .append(Gdx.graphics.getWidth()
						// +" * "+Gdx.graphics.getHeight())
						// .append("\n")

						.append(VERSION_CODE + "=").append(pi.versionCode)
						.append("\n").append("SDK_VERSION" + "=")
						.append(Build.VERSION.SDK_INT).append("\n")
						.append("RELEASE" + "=").append(Build.VERSION.RELEASE)
						.append("\n");
			}
		} catch (NameNotFoundException e) {
			LogUtils.i("Error while collect package info" + e);
		}

		String imsi = "unknow";
		String imei = "unknow";

		TelephonyManager telMgr = (TelephonyManager) ctx
				.getSystemService(Context.TELEPHONY_SERVICE);
		if (telMgr != null) {
			imsi = telMgr.getSubscriberId() != null ? telMgr.getSubscriberId()
					: "unknow";
			imei = telMgr.getDeviceId() != null ? telMgr.getDeviceId()
					: "unknow";

			sb.append("Globe.REQUEST_HEADER_IMSI" + "=")
					// IMSI
					.append(imsi).append("\n")
					.append("Globe.REQUEST_HEADER_IMEI" + "=")// IMEI
					.append(imei).append("\n");
		}
		Field[] fields = Build.class.getDeclaredFields();
		for (Field field : fields) {
			try {
				field.setAccessible(true);
				sb.append(field.getName() + "=")// 设备信息
						.append(field.get(null)).append("\n");
			} catch (Exception e) {
				LogUtils.i("UEHandler" + "Error while collect crash info", e);
			}
		}

	}

	/**
	 * 开辟子线程弹出提示
	 * 
	 * @param ex
	 * @return
	 */
	private boolean handleException(final String showText, Throwable ex) {
		if (ex == null) {
			return true;
		}
		new Thread() {
			@Override
			public void run() {
				Looper.prepare();
				Toast.makeText(softApp.getApplicationContext(), showText,
						Toast.LENGTH_LONG).show();
				Looper.loop();
			}
		}.start();
		return true;
	}

}
